package com.bsb.biz.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.authz.permission.WildcardPermission;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.bsb.base.common.config.Const;
import com.bsb.base.mapper.SysResourceMapper;
import com.bsb.base.model.SysResource;
import com.bsb.base.model.SysResourceExample;
import com.bsb.base.model.SysResource.ResourceType;
import com.bsb.base.model.SysResourceExample.Criteria;




@Service
public class SysResourceService{
	
	@Resource
	private SysResourceMapper sysResourceMapper;
	@Resource
	private SysUserService sysUserService;
	
	public void addSysResource(SysResource sysResource) {
		sysResourceMapper.insertSelective(sysResource);
	}
	
	public void delSysResourceById(Long id) {
		sysResourceMapper.deleteByPrimaryKey(id);
	}
	
	public void updateSysResource(SysResource sysResource) {
		sysResourceMapper.updateByPrimaryKeySelective(sysResource);
	}
	
	public void updateSysResourceByExample(SysResource sysResource,SysResourceExample sysResourceExample){
	    sysResourceMapper.updateByExampleSelective(sysResource,sysResourceExample);
	}
	
	public SysResource getSysResourceById(Long id) {
		return sysResourceMapper.selectByPrimaryKey(id);
	}
	
	public List<SysResource> getPageSysResource(SysResourceExample sysResourceExample) {
		return sysResourceMapper.selectPage(sysResourceExample);
	}
	
	public int countSysResource(SysResourceExample sysResourceExample) {
		return sysResourceMapper.countByExample(sysResourceExample);
	}
	
	public List<SysResource> selectByExample(SysResourceExample example){
	    return sysResourceMapper.selectByExample(example);
	}

	public Set<String> findPermissions(Set<Long> resourceIds) {
		Set<String> permissions = new HashSet<String>();
        for(Long resourceId : resourceIds) {
        	SysResource resource = getSysResourceById(resourceId);
            if(resource != null && !StringUtils.isEmpty(resource.getPermission())) {
                permissions.add(resource.getPermission());
            }
        }
        return permissions;
	}
	
	public Set<String> findAllPermissions() {
		Set<String> permissions = new HashSet<String>();
		List<SysResource> resources = sysResourceMapper.selectByExample(null);
        for(SysResource resource : resources) {
            if(resource != null && !StringUtils.isEmpty(resource.getPermission())) {
                permissions.add(resource.getPermission());
            }
        }
        return permissions;
	}
	
	public List<SysResource> findMenus(Set<String> permissions) {
        List<SysResource> allResources = findMenusByPid(1);
        List<SysResource> menus = new ArrayList<SysResource>();
        for(SysResource resource : allResources) {
//            if(resource.isRootNode()) {
//                continue;
//            }
            if(resource.getType() != SysResource.ResourceType.menu) {
                continue;
            }
            if(!hasPermission(permissions, resource)) {
                continue;
            }
            Long id = resource.getId();
            List<SysResource> findMenusByPid = findMenusByPid(id);
            List<SysResource> childMenus = new ArrayList<SysResource>();
            for (SysResource sysResource : findMenusByPid) {
            	if(sysResource.getType() != SysResource.ResourceType.menu) {
                    continue;
                }
                if(!hasPermission(permissions, sysResource)) {
                    continue;
                }
                childMenus.add(sysResource);
                resource.setChildList(childMenus);
			}
            menus.add(resource);
        }
        return menus;
    }

	public List<SysResource> findMenusByPid(long pid) {
		SysResourceExample example = new SysResourceExample();
        Criteria criteria = example.createCriteria();
        criteria.andParent_idEqualTo(pid);
        criteria.andTypeEqualTo(ResourceType.menu.toString());
        example.setOrderByClause("concat(parent_ids, id) asc");
		List<SysResource> allResources = sysResourceMapper.selectByExample(example );
		return allResources;
	}
	
    private boolean hasPermission(Set<String> permissions, SysResource resource) {
        if(StringUtils.isEmpty(resource.getPermission())) {
            return true;
        }
        for(String permission : permissions) {
            WildcardPermission p1 = new WildcardPermission(permission);
            WildcardPermission p2 = new WildcardPermission(resource.getPermission());
            if(p1.implies(p2) || p2.implies(p1)) {
                return true;
            }
        }
        return false;
    }

	public void delResource(Long id) {
		SysResource selectByPrimaryKey = sysResourceMapper.selectByPrimaryKey(id);
		sysResourceMapper.deleteByPrimaryKey(id);
		SysResourceExample example = new SysResourceExample();
		Criteria criteria = example.createCriteria();
		criteria.andParent_idsLike(selectByPrimaryKey.makeSelfAsParentIds()+"%");
		sysResourceMapper.deleteByExample(example );
	}
	
	public List<SysResource> getUserMenuList(Long userId) {
		//系统管理员，拥有最高权限
		if(userId == Const.SUPER_ADMIN){
			return getAllMenuList(null);
		}
		
		//用户菜单列表
		List<Long> menuIdList = sysUserService.queryAllMenuId(userId);
		return getAllMenuList(menuIdList);
	}
	
	public List<SysResource> queryListParentId(Long parentId) {
		return sysResourceMapper.queryListParentId(parentId);
	}
	
	public List<SysResource> queryListParentId(Long parentId, List<Long> menuIdList) {
		List<SysResource> menuList = queryListParentId(parentId);
		if(menuIdList == null){
			return menuList;
		}
		
		List<SysResource> userMenuList = new ArrayList<>();
		for(SysResource menu : menuList){
			if(menuIdList.contains(menu.getId())){
				userMenuList.add(menu);
			}
		}
		return userMenuList;
	}
	
	/**
	 * 获取所有菜单列表
	 */
	private List<SysResource> getAllMenuList(List<Long> menuIdList){
		//查询根菜单列表
		List<SysResource> menuList = queryListParentId(1L, menuIdList);
		//递归获取子菜单
		getMenuTreeList(menuList, menuIdList);
		
		return menuList;
	}

	/**
	 * 递归
	 */
	private List<SysResource> getMenuTreeList(List<SysResource> menuList, List<Long> menuIdList){
		List<SysResource> subMenuList = new ArrayList<SysResource>();
		
		for(SysResource entity : menuList){
			//目录
			if(entity.getType() == SysResource.ResourceType.catalog){
				entity.setChildList(getMenuTreeList(queryListParentId(entity.getId(), menuIdList), menuIdList));
			}
			subMenuList.add(entity);
		}
		
		return subMenuList;
	}
	
	

}
